package com.qire.manhua.view.comicReader.renderer;

import android.content.Context;
import android.graphics.Bitmap;

import com.qire.common.SummerApp;
import com.qire.common.utils.EquipmentInfoUtil;
import com.qire.common.utils.FileManager;
import com.qire.manhua.view.comicReader.renderer.core.BitmapCache;
import com.qire.manhua.view.comicReader.renderer.core.BitmapCache.ImageCacheParams;
import com.qire.manhua.view.comicReader.renderer.core.BitmapDecoder;
import com.qire.manhua.view.comicReader.renderer.core.BytesBufferPool;


/**
 * 漫画图片缓存
 */
public class ComicPictureCache implements IResourceCache {

	/** 全局唯一单例缓存 */
	public static final ComicPictureCache CACHE = new ComicPictureCache(0f, 0, 0, true);

	private static final int BYTES_BUFFER_POOL_SIZE = 4;
	private static final int BYTES_BUFFER_SIZE = 200 * 1024;
	private static final BytesBufferPool sMicroThumbBufferPool = new BytesBufferPool(BYTES_BUFFER_POOL_SIZE, BYTES_BUFFER_SIZE);

	private final BitmapCache mImageCache;

	/**
	 * 图片资源缓存构造函数，需要指定内存缓存大小及磁盘缓存大小。如果内存缓存即没有指定百分比大小也没指定固定值大小则启用默认值。
	 * 默认值按 android系统分配给每个apk内存的大小的 40% 来分配。
	 * @param memCacheSizePercent 内存缓存基于android系统分配给每个apk内存的大小的百分比大小，如果设置优先启用
	 * @param memCacheSize 内存缓存固定值大小，如果没有设置百分比则启用固定值大小，如果固定值大小小于2M 则启用默认百分比来设置
	 * @param diskCacheSize 磁盘大小，必须大于 5 M 否则使用默认大小为50M
	 * @param recycleImmediately 是否立即回收内存 true 立即回收， false 在不够空间时回收。
	 */
	private ComicPictureCache(float memCacheSizePercent, int memCacheSize, int diskCacheSize, boolean recycleImmediately) {

		Context appContext = SummerApp.summerApp().getApplicationContext();

		// 磁盘缓存路径
		String cachePath = FileManager.allotComicDiskCacheFolder().getAbsolutePath();

		ImageCacheParams imageCacheParams = new ImageCacheParams(cachePath);

		if(memCacheSizePercent > 0.05 && memCacheSizePercent < 0.8) {
			// 如果百分比方案指定优先百分比
			imageCacheParams.setMemCacheSizePercent(appContext, memCacheSizePercent);
		} else if(memCacheSize > 1024 * 1024 * 2) {
			// 如果百分比没有但指定了具体大小
			imageCacheParams.setMemCacheSize(memCacheSize);
		} else {
			// 如果都没指定使用默认值
			imageCacheParams.setMemCacheSizePercent(appContext, 0.4f);//0.3f);
		}

		if(diskCacheSize > 1024 * 1024 * 5) {
			imageCacheParams.setDiskCacheSize(diskCacheSize);
		}

		imageCacheParams.setRecycleImmediately(recycleImmediately);

		//初始化bitmap缓存
		mImageCache = new BitmapCache(imageCacheParams);
	}

	/**
	 * 释放缓存
	 */
	public void release () {
		mImageCache.close();
	}


	/** 根据 key 从内存缓存中获取bitmap */
	private Bitmap getBitmapFromMemoryCache(String key) {
		return mImageCache == null ? null : mImageCache.getBitmapFromMemoryCache(key);
	}

	/** 根据 key 从磁盘缓存中获取bitmap, 注意这里有io操作，最好不要放在ui线程执行 */
	private Bitmap getBitmapFromDiskCache(String key) {

		BytesBufferPool.BytesBuffer buffer = sMicroThumbBufferPool.get();
		Bitmap b = null;
		try {
			boolean found = mImageCache.getImageData(key, buffer);
			if ( found && buffer.length - buffer.offset > 0) {

				// 判断是否给定宽高来决定使用 注释掉的还是非注释代码来解码bitmap
				b = BitmapDecoder.decodeSampledBitmapFromByteArray(buffer.data, buffer.offset, buffer.length, EquipmentInfoUtil.getScreenWidth(), EquipmentInfoUtil.getScreenHeight());
//				b = BitmapFactory.decodeByteArray(buffer.data, buffer.offset, buffer.length);
			}
		} finally {
			sMicroThumbBufferPool.recycle(buffer);
		}
		return b;
	}


	/**
	 * 注意这里有io操作，最好不要放在ui线程执行:
	 * 1. 优先查找内存
	 * 2. 内存没有在查找磁盘缓存
	 * @param key 图片Key
	 * @return 内存缓存 和 磁盘缓存都没有则返回null
	 */
	@Override
	public Bitmap getBitmapFromCache(String key) {
		Bitmap bitmap  = getBitmapFromMemoryCache(key);
		if(bitmap != null) {
			return bitmap;
		}
		return getBitmapFromDiskCache(key);
	}

	@Override
	public Bitmap saveBitmapToCache(String key, byte[] data) {
		if(data == null || data.length <= 0) {
			return null;
		}

		mImageCache.addToDiskCache(key, data);

		// 判断是否给定宽高来决定使用 注释掉的还是非注释代码来解码bitmap
		return BitmapDecoder.decodeSampledBitmapFromByteArray(data, 0, data.length, EquipmentInfoUtil.getScreenWidth(), EquipmentInfoUtil.getScreenHeight());
//		return BitmapFactory.decodeByteArray(data, 0, data.length);
	}

}
